﻿using CefSharp;
using CodeGenerateEngine.Serv;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace CodeGenerateEngine.SchemeFactory
{
    /// <summary>
    /// 本地接口访问服务
    /// </summary>
    internal class ServiceDataSchemeHandlerFactory
    {
        private static List<RouteConfiguration> _routes;

        private static List<RouteConfiguration> routes
        {
            get
            {
                if (_routes == null)
                {
                    _routes = new List<RouteConfiguration>();
                }
                return _routes;
            }
        }

        public static CefCustomScheme GetInstance(string SchemeName, string DomainName)
        {
            // 创建Route
            ImportDataServiceAssembly();
            var scheme = new CefCustomScheme()
            {
                SchemeName = SchemeName,
                DomainName = DomainName,
                SchemeHandlerFactory = new ApiSchemeHandler()
            };
            return scheme;
        }



        /// <summary>
        /// 注册数据服务
        /// </summary>
        public static void ImportDataServiceAssembly()
        {
            var services = Assembly.GetEntryAssembly().GetTypes().Where(x => x.IsSubclassOf(typeof(DataService)));

            foreach (var service in services)
            {
                if (!service.IsSubclassOf(typeof(DataService)))
                {
                    continue;
                }
                var instance = (DataService)Activator.CreateInstance(service);
                ImportDataService(instance);
            }
        }

        private static void ImportDataService<T>(T instance) where T : DataService
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(T), $"Argument must not be null.");
            }

            var type = instance.GetType();

            if (type.Name.EndsWith(Common.AppServConfig.SERVICE_SUFFIX))
            {
                var serviceName = type.Name.Substring(0, type.Name.LastIndexOf(Common.AppServConfig.SERVICE_SUFFIX));
                // 获取返回至为IResourceHandler ，所有方法
                var actions = type.GetMethods().Where(x => x.ReturnType.IsAssignableFrom(typeof(IResourceHandler)));
                foreach (var actionInfo in actions)
                {
                    var actionParams = actionInfo.GetParameters().Select(x => Expression.Parameter(x.ParameterType, x.Name)).ToArray();
                    var caller = Expression.Call(Expression.Constant(instance), actionInfo, actionParams);
                    var actionDelegate = Expression.Lambda(caller, actionParams).Compile();
                    if (!(actionDelegate is Func<IRequest, IResourceHandler>))
                    {
                        continue;
                    }
                    // 添加路由
                    routes.Add(new RouteConfiguration($"{serviceName}/{actionInfo.Name}", actionDelegate as Func<IRequest, IResourceHandler>));
                }
            }
        }

        internal class ApiSchemeHandler : ISchemeHandlerFactory
        {
            public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
            {
                var pathUri = new Uri(request.Url);
                string relativePath = pathUri.LocalPath.Trim('/');
                var route = routes.SingleOrDefault(x => x.RoutePath.Equals(relativePath, StringComparison.CurrentCultureIgnoreCase));
                if (route == null)
                {
                    return ResourceHandler.ForErrorMessage($"{request.Url} 404", System.Net.HttpStatusCode.NotFound);
                }
                try
                {
                    var response = route.Execute(request);
                    if (response == null)
                    {
                        return ResourceHandler.ForErrorMessage($"{relativePath}执行异常", System.Net.HttpStatusCode.InternalServerError);
                    }
                    else
                    {
                        return response;
                    }
                }
                catch (Exception ex)
                {
                    string message = $"{relativePath}执行异常" + Environment.NewLine + ex.Message;
                    return ResourceHandler.ForErrorMessage($"{relativePath}执行异常", System.Net.HttpStatusCode.InternalServerError);
                }
                //return ResourceHandler.ForErrorMessage($"{request.Url} 请求地址无效", System.Net.HttpStatusCode.NotFound);
            }
        }

        internal class RouteConfiguration
        {

            public string RoutePath { get; }
            private Func<IRequest, IResourceHandler> RequestHandler { get; }

            public RouteConfiguration(string routePath, Func<IRequest, IResourceHandler> handler)
            {
                RoutePath = routePath;
                RequestHandler = handler;
            }

            public IResourceHandler Execute(IRequest request)
            {
                return RequestHandler?.Invoke(request);
            }
        }
    }

}
